package com.iori.common.db.dbctrl;

import java.util.ArrayList;
import java.util.List;

import org.apache.regexp.ex.RE;

/**
 * [クラス名]<br>
 * SQLファイルローダー<br>
 * <br>
 * [機能概要]<br>
 * sql retouch<br>
 * <br>
 * [変更履歴]<br>
 * 2007/11/12 ver1.00 新規作成 Liuww<br>
 * <br>
 *
 * @author Liuww
 * @version 1.00
 */
public class SqlRetouch {

	/**
	 * パラメータを意味するキーワード（正規表現文字）
	 */
	private static final String VARIABLE_KEYWORD = ":[\\w|\\[|\\]]+";

	/**
	 * #を意味するキーワード（正規表現文字）
	 */
	private static final String NAKAKAKKO_KEYWORD = "#[\\w|\\[|\\]]+";

	/**
	 * SQL文置き換え部を意味するキーワード（正規表現文字）
	 */
	private static final String REPLACE_KEYWORD = "(\\{):\\w+ .*?(\\})";

	public static SqlBrokenModel doRetouch(String sql){
		SqlBrokenModel sqlBroken = new SqlBrokenModel();
		sqlBroken.setType(getType(sql));
		sqlBroken.setOriginalSql(sql);
		List sqlSegment = new ArrayList();
		getSqlSegmentList(sql , sqlSegment);
		sqlBroken.setSqlSegmentList(sqlSegment);
		return sqlBroken;
	}

	private static void getSqlSegmentList(String sql, List sqlSegment){

		if(sql == null || sql.length() == 0){
			return;
		}

		//「{」的位置
		int pointIGETA = -1;

		//「#」的位置
		int pointNAKAKAKKO = -1;

		RE rReplace = new RE(REPLACE_KEYWORD);

		if(rReplace.match(sql, 0)){
			pointIGETA = rReplace.getParenStart(0);
		}

		RE rNAKAKAKKO = new RE(NAKAKAKKO_KEYWORD);
		if(rNAKAKAKKO.match(sql, 0)){
			pointNAKAKAKKO = rNAKAKAKKO.getParenStart(0);
		}

		if((pointIGETA < pointNAKAKAKKO && pointIGETA != -1) || (pointIGETA != -1 && pointNAKAKAKKO == -1)){
			if(pointIGETA == 0){ //begin with "{"
				String tempSqlSeg = sql.substring(rReplace.getParenStart(0), rReplace.getParenEnd(0));
				RE rKey = new RE(":\\w+");
				String conditionName = null;
				if (rKey.match(tempSqlSeg)) {
					conditionName = tempSqlSeg.substring(rKey.getParenStart(0), rKey.getParenEnd(0));
				}
				tempSqlSeg = tempSqlSeg.substring(rKey.getParenEnd(0) , rReplace.getParenEnd(0)-1);
				addSqlElementModel(tempSqlSeg,conditionName , SqlElementModel.TYPE_IGETA , sqlSegment);
				sql = sql.substring(rReplace.getParenEnd(0));
			}else{
				String tempSqlSeg = sql.substring(0, pointIGETA);
				addSqlElementModel(tempSqlSeg,null , SqlElementModel.TYPE_NORMAL,sqlSegment);
				sql = sql.substring(pointIGETA);
			}
		}else if(pointNAKAKAKKO != -1){		//"#"
			if(pointNAKAKAKKO == 0){
				String tempSqlSeg = sql.substring(rNAKAKAKKO.getParenStart(0), rNAKAKAKKO.getParenEnd(0));
				addSqlElementModel(null,tempSqlSeg , SqlElementModel.TYPE_NAKAKAKKO,sqlSegment);
				sql = sql.substring(rNAKAKAKKO.getParenEnd(0));
			}else{
				String tempSqlSeg = sql.substring(0, pointNAKAKAKKO);
				addSqlElementModel(tempSqlSeg,null , SqlElementModel.TYPE_NORMAL,sqlSegment);
				sql = sql.substring(pointNAKAKAKKO);
			}
		}else{
			addSqlElementModel(sql,null , SqlElementModel.TYPE_NORMAL,sqlSegment);
			sql = "";
		}
		getSqlSegmentList(sql , sqlSegment);
	}

	private static void addSqlElementModel(String sqlSegment, String conditionName , int type, List sqlSegmentList){
		//if(type == SqlElementModel.TYPE_NORMAL && (sqlSegment == null || sqlSegment.trim().equals(""))){
		//	return;
		//}
		SqlElementModel sqlElementModle = new SqlElementModel();
		sqlElementModle.setConditionName(conditionName);
		sqlElementModle.setType(type);
		if(type == SqlElementModel.TYPE_NORMAL){
			RE pattern = new RE(VARIABLE_KEYWORD);
			List paraList = new ArrayList(1);
			while (pattern.match(sqlSegment)) {
				String innerSql = sqlSegment.substring(pattern.getParenStart(0), pattern.getParenEnd(0));
				paraList.add(innerSql);
				sqlSegment = pattern.subst(sqlSegment, "?", RE.REPLACE_FIRSTONLY);
			}
			sqlElementModle.setSqlParaName(paraList);
			sqlElementModle.setSqlContent(sqlSegment);
		}else if(type == SqlElementModel.TYPE_IGETA){
			List sqlElements = new ArrayList(1);
			getSqlSegmentList(sqlSegment, sqlElements);
			sqlElementModle.setSqlElements(sqlElements);
		}
		sqlSegmentList.add(sqlElementModle);
	}

	private static int getType(String sql) {
		int result = DataAccessor.STORED;
		if (sql.trim().toLowerCase().indexOf("select ") == 0) {
			result = DataAccessor.QUERY;
		} else if (sql.trim().toLowerCase().indexOf("insert ") == 0) {
			result = DataAccessor.DML;
		} else if (sql.trim().toLowerCase().indexOf("update ") == 0) {
			result = DataAccessor.DML;
		} else if (sql.trim().toLowerCase().indexOf("delete ") == 0) {
			result = DataAccessor.DML;
		}
		return result;
	}
}
